﻿using Unikado.PHPLibs.Tokenizer.Types;

namespace Unikado.PHPLibs.Tokenizer
{

    /// <summary>
    /// A PHP Token.
    /// </summary>
    /// <remarks>
    /// A token is a fundamental element of some PHP code.
    /// <para>
    /// It defines the code, the spaces after the code, 3 types with different granularity,
    /// the linenumber of the token (thisis the number of the line where the token starts),
    /// The blocklevel of the token, the condition level (it means inside (…) round brackets),
    /// the Square level (inside […] square brackets), the index of the token inside the
    /// owning collection and a flag if its after a linebreak.
    /// </para>
    /// <para>
    /// For example the following code:
    /// </para>
    /// <code>
    /// &lt;?php
    ///   echo 'Hello world';
    /// ?&gt;
    /// </code>
    /// <para>
    /// will produce this tokens (code only for this case)
    /// </para>
    /// <list type="bullet">
    /// <item>«<b>&lt;?php</b>»</item>
    /// <item>«<b>\n  </b>»</item>
    /// <item>«<b>echo </b>»</item>
    /// <item>«<b>'Hello world!'</b>»</item>
    /// <item>«<b>;</b>»</item>
    /// <item>«<b>\n</b>»</item>
    /// <item>«<b>?&gt;</b>»</item>
    /// </list>
    /// </remarks>
    public class Token
    {

        #region - - - - - -   P R I V A T E   F I E L D S   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        private string code;

        #endregion

        #region - - - - - -   P U B L I C   P R O P E R T I E S   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        /// <summary>
        /// The code of the current token
        /// </summary>
        public string Code
        {
            get { return code; }
            internal set
            {
                code = value.Replace("\r\n", "\n");
                LinebreakCount = code.Split('\n').Length - 1;
            }
        }
        /// <summary>
        /// Returns the <see cref="Code"/> with appended <see cref="SpaceAfter"/>
        /// </summary>
        public string Text
        {
            get { return Code + SpaceAfter; }
        }
        /// <summary>
        /// The rough type of this token (not much detailed)
        /// </summary>
        public TypeRough RoughType { get; internal set; }
        /// <summary>
        /// The normal type of this token (its more detailed)
        /// </summary>
        public TypeNormal NormalType { get; internal set; }
        /// <summary>
        /// The fine type of this token. Its the most detailed type.
        /// </summary>
        public TypeFine FineType { get; internal set; }
        /// <summary>
        /// Returns how many line breaks ar inside the <see cref="Code"/>.
        /// </summary>
        public int LinebreakCount { get; private set; }
        /// <summary>
        /// This are the spaces after the current token
        /// </summary>
        public string SpaceAfter { get; internal set; }
        /// <summary>
        /// The number of the current token code line (1-n)
        /// </summary>
        public int LineNumber { get; internal set; }
        /// <summary>
        /// The depth of the blocklevel for this token. Each blocklevel is incremented by the <c>{</c>
        /// character and decremented by <c>}</c>
        /// </summary>
        public int Blocklevel { get; internal set; }
        /// <summary>
        /// The depth of the condition level for this token. Each condition level is incremented by the <c>(</c>
        /// character and decremented by <c>)</c>
        /// </summary>
        public int Conditionlevel { get; internal set; }
        /// <summary>
        /// The depth of the square bracket level for this token. Each square bracket level is incremented by the <c>[</c>
        /// character and decremented by <c>]</c>
        /// </summary>
        public int Squarelevel { get; internal set; }
        /// <summary>
        /// The Index of the Token inside the token collection.
        /// </summary>
        public int Index { get; internal set; }
        /// <summary>
        /// Returns, if the current token is the first after a line break.
        /// </summary>
        public bool IsAfterLinebreak { get; internal set; }

        #endregion

        #region - - - - - -   C O N S T R U C T O R S   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        internal Token(string codeString="")
        {
            Code = codeString;
            SpaceAfter = "";
            LineNumber = 1;
            Blocklevel = 0;
            Conditionlevel = 0;
            Squarelevel = 0;
            RoughType = TypeRough.None;
            NormalType = TypeNormal.None;
            FineType = TypeFine.None;
            Index = 0;
        }
        internal Token(string codeString, TypeRough t1, TypeNormal t2, TypeFine t3, string space, int lnum, int blev, int clev, int slev)
        {
            Code = codeString;
            SpaceAfter = space;
            LineNumber = lnum;
            Blocklevel = blev;
            Conditionlevel = clev;
            Squarelevel = slev;
            RoughType = t1;
            NormalType = t2;
            FineType = t3;
            Index = 0;
        }

        #endregion

        #region - - - - - -   P U B L I C   M E T H O D S   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        /// <summary>
        /// Returns the value of <see cref="Text"/>.
        /// </summary>
        /// <returns>string</returns>
        public override string ToString()
        {
            return Text;
        }

        #endregion

    }

}